﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;
using ColorUtilities;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;
using System.Text;
using System.Windows.Markup;
using System.IO;
using System.IO.IsolatedStorage;


namespace PivotViewerBase
{
    public static class CONSTANTS
    {
        internal const string PALLETTES = "Pallettes";
        internal const string EXT = ".pallette.txt";

        internal const string NEWPALLETTE_FILENAME = "New Pallette";

        internal const string NEWPALLETTE_FG = "Lime";
        internal const string NEWPALLETTE_BG = "Plum";

        internal const string NEWPALLETTE_FG_LIST = "DarkRed,AntiqueWhite,Yellow,SpringGreen";
        internal const string NEWPALLETTE_BG_LIST = "HotPink,Coral,CornflowerBlue,YellowGreen,Goldenrod";

    }

    public partial class ColorSchemeDesigner : Page
    {

        MVVM mvvm = new MVVM();

        private NamedColorsLegendsList _colorsList;

        public NamedColorsLegendsList colorsList
        {
            get { return _colorsList; }
            set { _colorsList = value; }
        }

        //public ObservableCollection<Color> chek = new ObservableCollection<Color>();

        //public Color MyForeGround { get; set; }


        public ColorSchemeDesigner()
        {
            colorsList = new NamedColorsLegendsList();
            this.Resources.Add("NamedColorsList", colorsList);


            mvvm.ForeGround = NamedColors.MistyRose;

            //this.Resources.Add("ForegroundColor", mvvm.ForeGround);


            InitializeComponent();


        }

        // Executes when the user navigates to this page.
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }

        private void Ellipse_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
        {

            Ellipse el = sender as Ellipse;
            //Get ellipse color
            System.Windows.Shapes.Shape sh = ((System.Windows.Shapes.Shape)(el));

            Color xx = ((System.Windows.Media.SolidColorBrush)(sh.Fill)).Color;

            //Set mvvm color
            mvvm.ForeGround = xx;
            mvvm.ForeGroundTitle = sh.Tag.ToString();

            //Refresh ellipseForeground color
            if (el.Name != this.ellipseForeground.Name)
                this.ellipseForeground.DataContext = mvvm;

            if (dataGrid1.CurrentColumn.DisplayIndex == 0)
            {
                //Refresh selected row's foreground color
                int iRow = dataGrid1.SelectedIndex;

                if (iRow > -1)
                {
                    mvvm.Pallette[iRow].Tiles[0].Colour = el.GetValue(TagProperty).ToString();
                    mvvm.Pallette[iRow].Tiles[0].Title = el.GetValue(TagProperty).ToString();
                }

                dataGrid1.ItemsSource = mvvm.Pallette;
            }
        }

        List<Ellipse> lstEllipses = new List<Ellipse>();
        private void Ellipse_DataContextChanged_1(object sender, DependencyPropertyChangedEventArgs e)
        {

        }

        private void Page_Loaded_1(object sender, RoutedEventArgs e)
        {
            //dataGrid1.AutoGenerateColumns = true;
            NewPallette();

            // dataGrid1.ItemsSource = arr;
        }

        private void NewPallette(int pnRows = -1)
        {

            mvvm.Pallette = ColourSwatch.GetData(pnRows);
            dataGrid1.AutoGenerateColumns = false;

            dataGrid1.Columns.Clear();

            //dataGrid1.Columns.Add(CreateTextColumn("Name", "Staff Name"));
            //dataGrid1.Columns.Add(CreateTextColumn("Department", "Company Department"));
            int TileCount = mvvm.Pallette[0].Tiles.Count;
            for (int i = 0; i < TileCount; i++)
            {
                dataGrid1.Columns.Add(CreateTemplateColumn(i, "Colour"));

            }


            dataGrid1.ItemsSource = mvvm.Pallette;

            StopEditPalleteFileName();
            txtPalletteFileName.Text = CONSTANTS.NEWPALLETTE_FILENAME;
        }


        private static DataGridTextColumn CreateTextColumn(string fieldName, string title)
        {
            DataGridTextColumn column = new DataGridTextColumn();
            column.Header = title;
            column.Binding = new System.Windows.Data.Binding(fieldName);
            column.Visibility = Visibility.Visible;
            return column;
        }

        private string CreateColumnTemplate(int index, string propertyName)
        {
            System.Text.StringBuilder CellTemp = new System.Text.StringBuilder();
            CellTemp.Append("<DataTemplate ");
            CellTemp.Append("xmlns='http://schemas.microsoft.com/winfx/");
            CellTemp.Append("2006/xaml/presentation' ");
            CellTemp.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>");
            CellTemp.Append(String.Format("<TextBlock Text='{{Binding Tiles[{0}].{1}}}'/>", index, propertyName));
            CellTemp.Append("</DataTemplate>");
            return CellTemp.ToString();
        }

        private string CreateEllipseColumnTemplate(int index, string propertyName)
        {
            System.Text.StringBuilder CellTemp = new System.Text.StringBuilder();
            CellTemp.Append("<DataTemplate ");
            CellTemp.Append("xmlns='http://schemas.microsoft.com/winfx/");
            CellTemp.Append("2006/xaml/presentation' ");
            CellTemp.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>");
            if (index == 0)
                CellTemp.Append(String.Format("<Grid Height='16' Width='16'  Background='Gray'><Ellipse ToolTipService.ToolTip='{{Binding Tiles[{0}].{1}}}' Height='10' Width='10' Fill='{{Binding Tiles[{0}].{1}}}'/></Grid>", index, propertyName));
            else
                CellTemp.Append(String.Format("<Grid><Rectangle ToolTipService.ToolTip='{{Binding Tiles[{0}].{1}}}' Height='16' Width='16' Fill='{{Binding Tiles[{0}].{1}}}'/><TextBlock  ToolTipService.ToolTip='{{Binding Tiles[{0}].{1}}}' HorizontalAlignment='Center' VerticalAlignment='Center' Text='{0}' FontSize='10' FontWeight='Bold' Foreground='{{Binding Tiles[0].{1}}}' /></Grid>", index, propertyName));

            CellTemp.Append("</DataTemplate>");
            return CellTemp.ToString();
        }

        private string CreateColumnEditTemplate(int index, string propertyName)
        {
            StringBuilder CellTemp = new StringBuilder();
            CellTemp.Append("<DataTemplate ");
            CellTemp.Append("xmlns='http://schemas.microsoft.com/winfx/");
            CellTemp.Append("2006/xaml/presentation' ");
            CellTemp.Append("xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>");
            CellTemp.Append(String.Format("<TextBox Text='{{Binding Tiles[{0}].{1}, Mode=TwoWay}}'/>", index, propertyName));
            CellTemp.Append("</DataTemplate>");
            return CellTemp.ToString();
        }

        private DataGridTemplateColumn CreateTemplateColumn(int i, string propName)
        {
            DataGridTemplateColumn column = new DataGridTemplateColumn();
            column.Header = String.Format("Tile#{0}.{1}", i, propName);
            if (i > 5) column.Visibility = Visibility.Collapsed;
            column.CellTemplate = (DataTemplate)XamlReader.Load(CreateEllipseColumnTemplate(i, propName)); //display template
            //column.CellEditingTemplate = (DataTemplate)XamlReader.Load(CreateColumnEditTemplate(i, propName)); //edit template


            return column;

        }

        private void Rectangle_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
        {
            if (sender is Rectangle)
            {
                Rectangle rect = sender as Rectangle;
                System.Windows.Shapes.Shape sh = ((System.Windows.Shapes.Shape)(rect));
                Color xx = ((System.Windows.Media.SolidColorBrush)(sh.Fill)).Color;

                //Set mvvm color
                mvvm.BackGround = xx;

                if (sh.Tag != null)
                    mvvm.BackGroundTitle = sh.Tag.ToString();

                if (!(rect.Name == this.rectangleBackground.Name))
                    this.rectangleBackground.DataContext = mvvm;


                if (dataGrid1.CurrentColumn.DisplayIndex > 0)
                {

                    //Refresh selected column's background color
                    int iCol = dataGrid1.CurrentColumn.DisplayIndex;
                    //int iRow = dataGrid1.SelectedIndex;

                    if (dataGrid1.SelectedIndex > -1)
                    {

                        for (int iRow = 0; iRow < mvvm.Pallette.Count(); iRow++)
                        {
                            mvvm.Pallette[iRow].Tiles[iCol].Colour = mvvm.BackGroundTitle;
                            mvvm.Pallette[iRow].Tiles[iCol].Title = mvvm.BackGroundTitle;
                        }

                        dataGrid1.ItemsSource = mvvm.Pallette;
                    }
                }
            }
        }

        private void btnAddForeGroundRow_Click(object sender, RoutedEventArgs e)
        {
            /* 
             * Use MVVM to add a row
             * Refresh datagrid DataContext so new row shows
             */
            mvvm.Pallette = ColourSwatch.AddRow();

            dataGrid1.ItemsSource = null;
            dataGrid1.ItemsSource = mvvm.Pallette;

        }

        private void btnRemoveForeGroundRow_Click(object sender, RoutedEventArgs e)
        {
            /*
             * Confirn that use wants to remove this foreground color / Row number
             * Use MVVM to remove row
             * 
             */

            if (dataGrid1.SelectedIndex > -1)
            {
                mvvm.Pallette = ColourSwatch.RemoveRow(dataGrid1.SelectedIndex);

                dataGrid1.ItemsSource = null;
                dataGrid1.ItemsSource = mvvm.Pallette;
            }
        }


        private void btnAddNewBackgoundColumn_Click(object sender, RoutedEventArgs e)
        {
            /* 
             * Use datagrid column's visibility
             *  so new column shows
             */
            foreach (DataGridColumn col in dataGrid1.Columns)

                if (col.Visibility == Visibility.Collapsed)
                {
                    col.Visibility = Visibility.Visible;
                    break;
                }


        }

        private void btnRemoveSelectedBackgoundColumn_Click(object sender, RoutedEventArgs e)
        {
            /*
             * Confirn that use wants to remove this background color / Column number
             * Use MVVM to remove column
             * 
             */

            if (dataGrid1.CurrentColumn.DisplayIndex > 0)
                dataGrid1.Columns[dataGrid1.CurrentColumn.DisplayIndex].Visibility = Visibility.Collapsed;
        }

        private void ellipseForeground_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {

        }

        private void Border_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
        {
            Ellipse_MouseLeftButtonUp_1(ellipseForeground, e);
        }


        /// <summary>
        /// Concaatenates the colors for visible datagrid columns
        /// </summary>
        /// <returns></returns>
        private string BackgroundPalletteColorsString()
        {
            string sBack = "";
            string sIndices = "";
            foreach (DataGridColumn col in dataGrid1.Columns.Skip(1))
                if (col.Visibility == Visibility.Visible)
                {
                    sBack += (sBack.Length > 0 ? "," : "") + mvvm.Pallette[0].Tiles[col.DisplayIndex].Title;
                    sIndices += (sIndices.Length > 0 ? "," : "") + col.DisplayIndex.ToString();
                }

            return sBack + "\r\n" + sIndices;
        }

        public string PalletteColorsString()
        {
            string sColors = mvvm.ForeGroundPalletteString()
                + "\r\n" + BackgroundPalletteColorsString()
                + "\r\n" + ellipseForeground.Tag.ToString()
                + "\r\n" + rectangleBackground.Tag.ToString()
                + "\r\n" + txtPalletteFileName.Text;
            return sColors;
        }



        private void btnCreateNewPallette_Click(object sender, RoutedEventArgs e)
        {
            NewPallette();
        }

        private void btnSavePalletteFile_Click(object sender, RoutedEventArgs e)
        {
            StartEditPalleteFileName();
        }

        private void btnOpenPalletteFile_Click(object sender, RoutedEventArgs e)
        {
            ShowFilesList();
        }

        private void ShowFilesList()
        {

            StopEditPalleteFileName();
            stkPalletteList.Visibility = Visibility.Visible;

            List<string> lstFiles = IsolatedStorage.FilesList(CONSTANTS.PALLETTES + "/*" + CONSTANTS.EXT, CONSTANTS.EXT).ToList<string>();

            cboPalletteFileNames.ItemsSource = lstFiles;
            cboPalletteFileNames.Focus();
            cboPalletteFileNames.IsDropDownOpen = true;
        }


        private void btnCopyPalletteColorsString_Click(object sender, RoutedEventArgs e)
        {
            string sColors = this.PalletteColorsString();
            Clipboard.SetText(sColors);
            MessageBox.Show(sColors, "Copied to the clipboard", MessageBoxButton.OK);

        }

        private void btnSavePalletteFileToIsolatedStorage_Click_1(object sender, RoutedEventArgs e)
        {
            StopEditPalleteFileName();

            string sFileName = CONSTANTS.PALLETTES + "/" + txtPalletteFileName.Text + CONSTANTS.EXT;
            byte[] buf = System.Text.Encoding.UTF8.GetBytes(PalletteColorsString());
            IsolatedStorage.WriteToStorage(sFileName, buf);

            MessageBox.Show("Saved " + sFileName);
        }


        private void cboPalletteFileNames_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (cboPalletteFileNames.SelectedIndex > -1)
            {
                txtPalletteFileName.Text = cboPalletteFileNames.SelectedValue.ToString();
                string sFileName = CONSTANTS.PALLETTES + "/" + txtPalletteFileName.Text + CONSTANTS.EXT;

                byte[] buf = IsolatedStorage.ReadFromStorage(sFileName);
                string sData = System.Text.Encoding.UTF8.GetString(buf, 0, buf.Count());
                RestorePalletteFromData(sData);
            }
            StopEditPalleteFileName();
        }

        private void RestorePalletteFromData(string sData)
        {
            string[] saData = sData.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            /// 0 - Foreground Colors
            /// 1 - Background Colors
            /// 2 - Visible Columns
            /// 3 - Foreground Pick
            /// 4 - Backround Pick
            /// 5 - Pallette Name
            /// 
            /// 

            if (saData.Length < 6) return;
            List<string> lstForegroundColors = saData[0].Split(',').ToList<string>();
            List<string> lstBackgroundColors = saData[1].Split(',').ToList<string>();
            List<string> lstVisibleColumns = saData[2].Split(',').ToList<string>();

            mvvm.ForeGround = NamedColors.GetColor(saData[3]);
            mvvm.BackGround = NamedColors.GetColor(saData[4]);




            /* First we create a new pallete
             * Then we poke our colors into the array
             * Then we show the visible columns
             * 
             */
            NewPallette(lstForegroundColors.Count());



            int TileCount = mvvm.Pallette[0].Tiles.Count;
            for (int iRow = 0; iRow < lstForegroundColors.Count(); iRow++)
            {
                mvvm.Pallette[iRow].Tiles[0].Colour = lstForegroundColors[iRow];
                mvvm.Pallette[iRow].Tiles[0].Title = lstForegroundColors[iRow];

                for (int i = 1; i < TileCount; i++)
                {
                    if (lstVisibleColumns.Contains(i.ToString()))
                    {
                        dataGrid1.Columns[i].Visibility = Visibility.Visible;
                        mvvm.Pallette[iRow].Tiles[i].Colour = lstBackgroundColors[lstVisibleColumns.IndexOf((i).ToString())];
                        mvvm.Pallette[iRow].Tiles[i].Title = lstBackgroundColors[lstVisibleColumns.IndexOf((i).ToString())];
                    }
                    else
                        dataGrid1.Columns[i].Visibility = Visibility.Collapsed;

                }
            }

            dataGrid1.ItemsSource = null;

            dataGrid1.ItemsSource = mvvm.Pallette;
            //dataGrid1.ItemsSource = mvvm.SetData(lstForegroundColors,lstBackgroundColors,lstVisibleColumns);
            txtPalletteFileName.Text = saData[5];



        }

        private void btnDletePalletteFile_Click_1(object sender, RoutedEventArgs e)
        {
            MessageBoxResult res = MessageBox.Show("Are you sure you want to delete this pallette?", "", MessageBoxButton.OKCancel);
            if (res == MessageBoxResult.OK)
            {
                string sFileName = CONSTANTS.PALLETTES + "/" + txtPalletteFileName.Text + CONSTANTS.EXT;
                IsolatedStorage.DeleteFromStorage(sFileName);

                ShowFilesList();
            }
        }

        private void dataGrid1_LoadingRow(object sender, DataGridRowEventArgs e)
        {

        }

        private void txtPalletteFileName_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                StopEditPalleteFileName();
            }
        }

        private void StopEditPalleteFileName()
        {
            stkPalletteFileNames.Visibility = Visibility.Visible;
            stkPalletteList.Visibility = Visibility.Collapsed;

            txtPalletteFileName.IsReadOnly = true;
            txtPalletteFileName.Background = new SolidColorBrush(Colors.Transparent);
            btnSavePalletteFileToIsolatedStorage.Visibility = Visibility.Collapsed;
            btnSavePalletteFile.Focus();

            if (txtPalletteFileName.Text == "New Pallette")
                btnDeletePalletteFile.Visibility = Visibility.Collapsed;
            else
                btnDeletePalletteFile.Visibility = Visibility.Visible;
        }

        private void StartEditPalleteFileName()
        {
            stkPalletteFileNames.Visibility = Visibility.Visible;
            stkPalletteList.Visibility = Visibility.Collapsed;

            txtPalletteFileName.IsReadOnly = false;
            txtPalletteFileName.Background = new SolidColorBrush(Colors.White);
            btnSavePalletteFileToIsolatedStorage.Visibility = Visibility.Visible;
            txtPalletteFileName.Focus();
        }

        private void Viewbox_SizeChanged_1(object sender, SizeChangedEventArgs e)
        {

        }


    }

    public class MVVM : INotifyPropertyChanged
    {
        public MVVM()
        { }

        private Color _ForeGround;
        public Color ForeGround
        {
            get { return _ForeGround; }
            set
            {
                _ForeGround = value;

                RaisePropertyChanged("ForeGround");
            }
        }

        private Color _BackGround = NamedColors.Plum;
        public Color BackGround
        {
            get { return _BackGround; }
            set
            {
                _BackGround = value;

                RaisePropertyChanged("BackGround");
            }
        }


        private string _ForeGroundTitle = "Lime";
        public string ForeGroundTitle
        {
            get { return _ForeGroundTitle; }
            set
            {
                _ForeGroundTitle = value;

                RaisePropertyChanged("ForeGroundTitle");
            }
        }

        private string _BackGroundTitle = "Plum";
        public string BackGroundTitle
        {
            get { return _BackGroundTitle; }
            set
            {
                _BackGroundTitle = value;

                RaisePropertyChanged("BackGroundTitle");
            }
        }

        private List<ColourSwatch> _pallette;
        public List<ColourSwatch> Pallette
        {
            get { return _pallette; }
            set
            {
                _pallette = value;
                RaisePropertyChanged("Pallette");
            }
        }

        /// <summary>
        /// Concatenates a fg colors csv string and a bg csv string with a semi-colon;
        /// </summary>
        /// <returns></returns>
        public string ForeGroundPalletteString()
        {
            string sFore = "";
            foreach (ColourSwatch cs in _pallette)
                sFore += (sFore.Length > 0 ? "," : "") + cs.Tiles[0].Title;

            return sFore;
        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

    }


    public class ColourSwatch
    {
        public ObservableCollection<Tile> Tiles { get; set; }
        static List<ColourSwatch> _pallette;
        /// <summary>
        /// This creates a new ColourSwatch List and populates it with three ColourSwatchs of 22 colors each
        /// Note that the first color in each ColourSwatch is the foreground color for the swatch.
        /// The remaining colors are background colors for the swatch.
        /// </summary>
        /// <returns></returns>
        public static List<ColourSwatch> GetData(int pnRows)
        {

            int nRows = pnRows;
            if (nRows == -1) nRows = CONSTANTS.NEWPALLETTE_FG_LIST.Split(',').Count();

            _pallette = new List<ColourSwatch>();
            for (int i = 0; i < nRows; i++)
            {
                ColourSwatch swatch = new ColourSwatch();
                ObservableCollection<Tile> tiles = new ObservableCollection<Tile>();
                for (int j = 0; j < 23; j++)
                {
                    string sTitle = NamedColors.NamedColorsNamesList[j];

                    if (pnRows == -1)
                        if (j == 0)
                            sTitle = CONSTANTS.NEWPALLETTE_FG_LIST.Split(',')[i];
                        else if (j - 1 < CONSTANTS.NEWPALLETTE_BG_LIST.Split(',').Count())
                            sTitle = CONSTANTS.NEWPALLETTE_BG_LIST.Split(',')[j - 1];

                    tiles.Add(new Tile() { Title = sTitle, Colour = sTitle });
                }
                swatch.Tiles = tiles;
                _pallette.Add(swatch);
            }
            // _pallette = Pallette;
            return _pallette;
        }

        public static List<ColourSwatch> AddRow()
        {
            ColourSwatch swatch = new ColourSwatch();
            ObservableCollection<Tile> tiles = new ObservableCollection<Tile>();
            //Add right number of columns
            for (int j = 0; j < _pallette[0].Tiles.Count(); j++)
            {
                //Color oColor = NamedColors.NamedColorsList[j];
                string sTitle = _pallette[0].Tiles[j].Title;
                tiles.Add(new Tile() { Title = sTitle, Colour = sTitle });
            }
            swatch.Tiles = tiles;
            _pallette.Add(swatch);
            return _pallette;

        }

        public static List<ColourSwatch> RemoveRow(int iRow)
        {
            _pallette.RemoveAt(iRow);
            return _pallette;
        }


    }

    public class Tile : INotifyPropertyChanged
    {
        public string Title { get; set; }
        private string _Colour;

        public string Colour
        {
            get { return _Colour; }
            set
            {
                _Colour = value;
                RaisePropertyChanged("Colour");
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

    }


}
